﻿using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;

/// <summary>
/// 方块管理器
/// </summary>
public class TileManager : MonoBehaviour
{
    public static TileManager Instance;

    // 关卡数据
    public LevelDataManager levelData;
    // 方块预制体
    public List<TileBase> tilePrefabs;
    // 方块父对象
    public Transform tilesParent;
    // 当前关卡方块
    public List<TileBase> levelTiles;

    // 方块底栏
    public TilesBarManager tilesBar;

    // 所有类型的方块
    [SerializeField]
    private List<TileBase> allTileType = new List<TileBase>();
    // 当前方块层
    private int currentTileLayer = 1;
    // 提示所需的方块数量
    private int hintNeddTileNum = 1;

    private void Awake()
    {
        Instance = this;
    }

    private void Start()
    {
        if (PlayerPrefs.GetInt("Current_Level", 1) < 11)
            CreateTileByLevel(levelData.levels[PlayerPrefs.GetInt("Current_Level", 1) - 1]);
        else
            CreateTileByLevel(levelData.levels[UnityEngine.Random.Range(10, 15)]);
    }

    /// <summary>
    /// 根据关卡生成方块
    /// </summary>
    /// <param name="level"> 关卡 </param>
    public void CreateTileByLevel(Level level)
    {
        ClearAllTiles();
        Debug.Log("生成关卡 " + level.name + " 方块，类型：" + level.createType);
        LevelAllTiles(level);
        switch (level.createType)
        {
            case TileCreateType.TileCreateType_1:
                CreateTileByType_1(level);
                break;
            case TileCreateType.TileCreateType_2:
                CreateTileByType_2(level);
                break;
            case TileCreateType.TileCreateType_3:
                CreateTileByType_3(level);
                break;
            case TileCreateType.TileCreateType_4:
                CreateTileByType_4(level);
                break;
            case TileCreateType.TileCreateType_5:
                CreateTileByType_5(level);
                break;
            case TileCreateType.TileCreateType_Up:

                break;
            case TileCreateType.TileCreateType_Bottom:

                break;
            case TileCreateType.TileCreateType_Left:

                break;
            case TileCreateType.TileCreateType_Right:

                break;
        }

    }

    /// <summary>
    /// 关卡所需的所有方块
    /// </summary>
    /// <param name="level"> 关卡 </param>
    private void LevelAllTiles(Level level)
    {
        allTileType.Clear();
        for (int i = 0; i < level.tileTypeNum.Count; i++)
        {
            for (int j = 0; j < level.tileTypeNum[i]; j++)
            {
                for (int l = 0; l < 3; l++)
                {
                    allTileType.Add(tilePrefabs[i]);
                }
            }
        }
        // 打乱方块排序
        System.Random random = new System.Random();
        List<TileBase> tempList = new List<TileBase>();
        foreach (TileBase item in allTileType)
        {
            tempList.Insert(random.Next(tempList.Count), item);
        }
        allTileType = tempList;
    }

    /// <summary>
    /// 方块生成类型_1
    /// </summary>
    private void CreateTileByType_1(Level level)
    {
        Debug.Log("生成类型_1");
        if (level.createRows.Count <= 0)
            return;
        while (allTileType.Count > 0)
        {
            for (int i = 0; i < level.createRows.Count; i++)
            {
                for (int j = 0; j < level.createRows[i].TilePos.Count - (currentTileLayer - 1); j++)
                {
                    allTileType[0].tileLayer = currentTileLayer;
                    allTileType[0].tilePosition = new Vector2(level.createRows[i].TilePos[j].x + (50 * (currentTileLayer - 1)), level.createRows[i].TilePos[j].y - (50 * (currentTileLayer - 1)));
                    GameObject newTile = Instantiate(allTileType[0].gameObject, tilesParent);
                    newTile.transform.localPosition = new Vector2(level.createRows[i].TilePos[j].x + (50 * (currentTileLayer - 1)), level.createRows[i].TilePos[j].y - (50 * (currentTileLayer - 1)));
                    levelTiles.Add(newTile.GetComponent<TileBase>());
                    allTileType.RemoveAt(0);
                    // 添加完成
                    if (allTileType.Count <= 0)
                    {
                        for (int l = 0; l < levelTiles.Count; l++)
                        {
                            levelTiles[l].TileInit();
                        }
                        Debug.Log("方块添加完成");
                        return;
                    }
                }
            }
            currentTileLayer++;
        }
    }

    /// <summary>
    /// 方块生成类型_2
    /// </summary>
    public void CreateTileByType_2(Level level)
    {
        Debug.Log("生成类型_2");
        if (level.createRows.Count <= 0)
            return;
        while (allTileType.Count > 0)
        {
            for (int i = 0; i < level.createRows.Count - (currentTileLayer - 1); i++)
            {
                for (int j = 0; j < level.createRows[i].TilePos.Count - (currentTileLayer - 1); j++)
                {
                    allTileType[0].tileLayer = currentTileLayer;
                    if (i % 2 == 1)
                    {
                        allTileType[0].tilePosition = new Vector2(level.createRows[i].TilePos[j].x + (50 * (currentTileLayer - 1)), level.createRows[i].TilePos[j].y + (55 * (currentTileLayer - 1)));
                        GameObject newTile = Instantiate(allTileType[0].gameObject, tilesParent);
                        newTile.transform.localPosition = new Vector2(level.createRows[i].TilePos[j].x + (50 * (currentTileLayer - 1)), level.createRows[i].TilePos[j].y + (55 * (currentTileLayer - 1)));
                        levelTiles.Add(newTile.GetComponent<TileBase>());
                        allTileType.RemoveAt(0);
                    }
                    else
                    {
                        allTileType[0].tilePosition = new Vector2(level.createRows[i].TilePos[j].x + (50 * (currentTileLayer - 1)), level.createRows[i].TilePos[j].y - (55 * (currentTileLayer - 1)));
                        GameObject newTile = Instantiate(allTileType[0].gameObject, tilesParent);
                        newTile.transform.localPosition = new Vector2(level.createRows[i].TilePos[j].x + (50 * (currentTileLayer - 1)), level.createRows[i].TilePos[j].y - (55 * (currentTileLayer - 1)));
                        levelTiles.Add(newTile.GetComponent<TileBase>());
                        allTileType.RemoveAt(0);
                    }

                    // 添加完成
                    if (allTileType.Count <= 0)
                    {
                        for (int l = 0; l < levelTiles.Count; l++)
                        {
                            levelTiles[l].TileInit();
                        }
                        Debug.Log("方块添加完成");
                        return;
                    }
                }
            }
            Debug.Log("方块层数 +1");
            currentTileLayer++;
        }
    }

    /// <summary>
    /// 方块生成类型_3
    /// </summary>
    public void CreateTileByType_3(Level level)
    {
        Debug.Log("生成类型_3");
        if (level.createRows.Count <= 0)
            return;
        while (allTileType.Count > 0)
        {
            for (int i = 0; i < level.createRows.Count - (currentTileLayer - 1); i++)
            {
                for (int j = 0; j < level.createRows[i].TilePos.Count - (currentTileLayer - 1); j++)
                {
                    if (currentTileLayer > 2 && (j == 1 || j == 2))
                        continue;
                    else if (currentTileLayer > 1 && j == 2)
                        continue;
                    allTileType[0].tileLayer = currentTileLayer;
                    allTileType[0].tilePosition = new Vector2(level.createRows[i].TilePos[j].x + (50 * (currentTileLayer - 1)), level.createRows[i].TilePos[j].y - (50 * (currentTileLayer - 1)));
                    GameObject newTile = Instantiate(allTileType[0].gameObject, tilesParent);
                    newTile.transform.localPosition = new Vector2(level.createRows[i].TilePos[j].x + (50 * (currentTileLayer - 1)), level.createRows[i].TilePos[j].y - (50 * (currentTileLayer - 1)));
                    levelTiles.Add(newTile.GetComponent<TileBase>());
                    allTileType.RemoveAt(0);
                    // 添加完成
                    if (allTileType.Count <= 0)
                    {
                        for (int l = 0; l < levelTiles.Count; l++)
                        {
                            levelTiles[l].TileInit();
                        }
                        Debug.Log("方块添加完成");
                        return;
                    }
                }
            }
            Debug.Log("方块层数 +1");
            currentTileLayer++;
        }
    }

    /// <summary>
    /// 方块生成类型_4
    /// </summary>
    public void CreateTileByType_4(Level level)
    {
        Debug.Log("生成类型_4");
        if (level.createRows.Count <= 0)
            return;
        while (allTileType.Count > 0)
        {
            for (int i = 0; i < level.createRows.Count; i++)
            {
                if (currentTileLayer == 2)
                {
                    if (i == 2 || i == level.createRows.Count - 1)
                        continue;
                }
                else if (currentTileLayer == 3)
                    if (i == 1 || i == 2 || i == level.createRows.Count - 1 || i == level.createRows.Count - 2)
                        continue;

                for (int j = 0; j < level.createRows[i].TilePos.Count; j++)
                {
                    if (currentTileLayer == 2)
                    {
                        if (j == 2 || j == level.createRows[i].TilePos.Count - 1)
                            continue;
                    }
                    else if (currentTileLayer == 3)
                        if (j == 1 || j == 2 || j == level.createRows[i].TilePos.Count - 1 || j == level.createRows[i].TilePos.Count - 2)
                            continue;
                    allTileType[0].tileLayer = currentTileLayer;
                    GameObject newTile = Instantiate(allTileType[0].gameObject, tilesParent);
                    newTile.transform.localPosition = new Vector2(level.createRows[i].TilePos[j].x + (50 * (currentTileLayer - 1)), level.createRows[i].TilePos[j].y - (55 * (currentTileLayer - 1)));
                    levelTiles.Add(newTile.GetComponent<TileBase>());
                    allTileType.RemoveAt(0);
                    // 添加完成
                    if (allTileType.Count <= 0)
                    {
                        for (int l = 0; l < levelTiles.Count; l++)
                        {
                            levelTiles[l].TileInit();
                        }
                        Debug.Log("方块添加完成");
                        return;
                    }
                }
            }
            Debug.Log("方块层数 +1");
            currentTileLayer++;
            if (currentTileLayer == 3)
            {
                // 额外方块
                if (level.extraTile.Count >= 0)
                {
                    for (int l = 0; l < level.extraTile.Count; l++)
                    {
                        Debug.Log("额外方块类型：" + level.extraTile[l].createType);
                        for (int s = 0; s < level.extraTile[l].createNum; s++)
                        {
                            allTileType[0].tileLayer = s + 1;
                            GameObject newTile = Instantiate(allTileType[0].gameObject, tilesParent);
                            switch (level.extraTile[l].createType)
                            {
                                case TileCreateType.TileCreateType_Up:
                                    newTile.transform.localPosition = new Vector2(level.extraTile[l].TilePos[0].x, level.extraTile[l].TilePos[0].y + (10 * s));
                                    Debug.Log("UP_" + newTile.transform.localPosition);
                                    break;
                                case TileCreateType.TileCreateType_Bottom:
                                    Debug.Log("Bottom");
                                    newTile.transform.localPosition = new Vector2(level.extraTile[l].TilePos[0].x, level.extraTile[l].TilePos[0].y - (10 * s));
                                    break;
                                case TileCreateType.TileCreateType_Left:
                                    Debug.Log("Left");
                                    newTile.transform.localPosition = new Vector2(level.extraTile[l].TilePos[0].x - (10 * s), level.extraTile[l].TilePos[0].y);
                                    break;
                                case TileCreateType.TileCreateType_Right:
                                    Debug.Log("Right");
                                    newTile.transform.localPosition = new Vector2(level.extraTile[l].TilePos[0].x + (10 * s), level.extraTile[l].TilePos[0].y);
                                    break;
                            }
                            levelTiles.Add(newTile.GetComponent<TileBase>());
                            allTileType.RemoveAt(0);
                            // 添加完成
                            if (allTileType.Count <= 0)
                            {
                                for (int i = 0; i < levelTiles.Count; i++)
                                {
                                    levelTiles[i].TileInit();
                                }
                                Debug.Log("方块添加完成");
                                return;
                            }
                        }
                    }
                }
            }
        }
    }

    /// <summary>
    /// 方块生成类型_5
    /// </summary>
    public void CreateTileByType_5(Level level)
    {
        Debug.Log("生成类型_5");
        if (level.createRows.Count <= 0)
            return;
        while (allTileType.Count > 0)
        {
            for (int i = 0; i < level.createRows.Count; i++)
            {
                for (int j = 0; j < level.createRows[i].TilePos.Count; j++)
                {
                    allTileType[0].tileLayer = currentTileLayer;
                    GameObject newTile = Instantiate(allTileType[0].gameObject, tilesParent);
                    newTile.transform.localPosition = new Vector2(level.createRows[i].TilePos[j].x, level.createRows[i].TilePos[j].y - (50 * (currentTileLayer - 1)));
                    levelTiles.Add(newTile.GetComponent<TileBase>());
                    allTileType.RemoveAt(0);
                    // 添加完成
                    if (allTileType.Count <= 0)
                    {
                        for (int l = 0; l < levelTiles.Count; l++)
                        {
                            levelTiles[l].TileInit();
                        }
                        Debug.Log("方块添加完成");
                        return;
                    }
                }
            }
            Debug.Log("方块层数 +1");
            currentTileLayer++;
            if (currentTileLayer == 4)
            {
                // 额外方块
                if (level.extraTile.Count >= 0)
                {
                    for (int l = 0; l < level.extraTile.Count; l++)
                    {
                        Debug.Log("额外方块类型：" + level.extraTile[l].createType);
                        for (int s = 0; s < level.extraTile[l].createNum; s++)
                        {
                            allTileType[0].tileLayer = s + 1;
                            GameObject newTile = Instantiate(allTileType[0].gameObject, tilesParent);
                            switch (level.extraTile[l].createType)
                            {
                                case TileCreateType.TileCreateType_Up:
                                    newTile.transform.localPosition = new Vector2(level.extraTile[l].TilePos[0].x, level.extraTile[l].TilePos[0].y + (10 * s));
                                    Debug.Log("UP_" + newTile.transform.localPosition);
                                    break;
                                case TileCreateType.TileCreateType_Bottom:
                                    Debug.Log("Bottom");
                                    newTile.transform.localPosition = new Vector2(level.extraTile[l].TilePos[0].x, level.extraTile[l].TilePos[0].y - (10 * s));
                                    break;
                                case TileCreateType.TileCreateType_Left:
                                    Debug.Log("Left");
                                    newTile.transform.localPosition = new Vector2(level.extraTile[l].TilePos[0].x - (10 * s), level.extraTile[l].TilePos[0].y);
                                    break;
                                case TileCreateType.TileCreateType_Right:
                                    Debug.Log("Right");
                                    newTile.transform.localPosition = new Vector2(level.extraTile[l].TilePos[0].x + (10 * s), level.extraTile[l].TilePos[0].y);
                                    break;
                            }
                            levelTiles.Add(newTile.GetComponent<TileBase>());
                            allTileType.RemoveAt(0);
                            // 添加完成
                            if (allTileType.Count <= 0)
                            {
                                for (int i = 0; i < levelTiles.Count; i++)
                                {
                                    levelTiles[i].TileInit();
                                }
                                Debug.Log("方块添加完成");
                                return;
                            }
                        }
                    }
                }
            }
        }
    }

    /// <summary>
    /// 清除所有方块
    /// </summary>
    public void ClearAllTiles()
    {
        for (int i = 0; i < levelTiles.Count; i++)
            levelTiles[i].TilePurging();
    }

    /// <summary>
    /// 撤销方块操作
    /// </summary>
    public void CancleTheTile()
    {
        AudioManager.Instance.PlayButtonSound();

        // 不存在上一步操作
        if (tilesBar.OperationTiles.Count <= 0)
            return;
        // 撤销操作
        tilesBar.OperationTiles[tilesBar.OperationTiles.Count - 1].TileCancle();
    }

    /// <summary>
    /// 重新洗牌
    /// </summary>
    public void ReshuffleForTiles()
    {
        AudioManager.Instance.PlayButtonSound();

        // 无法洗牌
        if (levelTiles.Count <= 2)
            return;
        // 记录位置
        for (int i = 0; i < levelTiles.Count; i++)
            levelTiles[i].SetOriginalPos();
        // 随机洗牌
        List<TileBase> temp = new List<TileBase>(levelTiles.ToArray());
        System.Random random = new System.Random();
        int randomNum;
        AudioManager.Instance.PlayReshuffleSound();
        while (temp.Count > 1)
        {
            randomNum = random.Next(1, temp.Count);

            temp[0].TileReshuffle(temp[randomNum].originalPos, temp[randomNum].tileLayer, levelTiles.IndexOf(temp[randomNum]));
            temp[randomNum].TileReshuffle(temp[0].originalPos, temp[0].tileLayer, levelTiles.IndexOf(temp[0]));
            Swap(levelTiles, levelTiles.IndexOf(temp[randomNum]), levelTiles.IndexOf(temp[0]));
            temp.RemoveAt(randomNum);
            temp.RemoveAt(0);
        }
    }

    /// <summary>
    /// 清除方块提示
    /// </summary>
    public void ClearTileHints()
    {
        // 无需提示
        if (levelTiles.Count <= 0 || tilesBar.suspendTiles.Count <= 0)
            return;
        Debug.Log("方块提示");
        Dictionary<TileType, int> needTile = tilesBar.GetTileTypeForNeed();
        hintNeddTileNum = 3 - needTile.ElementAt(0).Value;
        Debug.Log("需要 " + needTile.ElementAt(0).Key + " 方块 " + hintNeddTileNum + " 个");
        for (int i = 0; i < levelTiles.Count; i++)
        {
            if (levelTiles[i].tileType == needTile.ElementAt(0).Key)
            {
                hintNeddTileNum--;
                levelTiles[i].TileHintMove();
                if (hintNeddTileNum <= 0)
                    return;
            }
        }
    }

    /// <summary>
    /// 元素位置互换
    /// </summary>
    private static List<T> Swap<T>(List<T> list, int index1, int index2)
    {
        var temp = list[index1];
        list[index1] = list[index2];
        list[index2] = temp;
        return list;
    }

}

/// <summary>
/// 方块生成类型
/// </summary>
public enum TileCreateType
{
    TileCreateType_1,
    TileCreateType_2,
    TileCreateType_3,
    TileCreateType_4,
    TileCreateType_5,
    TileCreateType_Up,
    TileCreateType_Bottom,
    TileCreateType_Left,
    TileCreateType_Right
}
